import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import matplotlib.pyplot as plt
import random
import imageio
import wordcloud
import datetime
from GUI import utils


class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # 窗口标题、图标、大小
        self.setWindowTitle('微博热门话题分析')
        self.setWindowIcon(QIcon('images/window_icon.png'))
        self.resize(1600, 950)

        # 窗口背景图片
        self.palette = QPalette()
        self.palette.setBrush(QPalette.Background, QBrush(QPixmap('images/background.jpg')))
        self.setPalette(self.palette)

        # 获取实时热搜数据的线程
        self.getRealTimeHotSearchThread = utils.GetRealTimeHotSearchThread()
        self.getRealTimeHotSearchThread.get_RealTimeHotSearch.connect(self.update_HotSearchTable)
        self.getRealTimeHotSearchThread.failure_signal.connect(self.failure_getHotSearch)

        # 获取历史热门表格数据的线程
        self.getTableDataThread = utils.GetTableDataThread()
        self.getTableDataThread.get_table_data.connect(self.load_HistoricalTopicTable_data)

        # 获取话题排行表格数据的线程
        self.getTopicListThread = utils.GetTopicListThread()
        self.getTopicListThread.get_topicList.connect(self.load_TopicCountTable_data)

        # 获取标签统计数据的线程
        self.getTagListThread = utils.GetTagListThread()
        self.getTagListThread.get_tagList.connect(self.create_barGraph)

        # 获取热词数据的线程
        self.getWordDictThread = utils.GetWordDictThread()
        self.getWordDictThread.get_wordDict.connect(self.create_wordcloud)

        # 表头
        self.HotSearch_attribute = ['排名', '热搜名称', '标签']

        self.HistoricalTopic_attribute = ['话题名称', '爬取时间', '排名', '阅读数', '标签', '主持人']

        self.TopicCount_attribute = ['热度总排名', '话题名称', '话题简介', '标签', '主持人']

        # 历史热门数据是否加载完成的标志
        self.init_HistoricalTopic_flag = False

        # 实时热搜表格
        self.HotSearch_model = QStandardItemModel()
        self.HotSearch_model.setHorizontalHeaderLabels(self.HotSearch_attribute)

        self.HotSearch_tableView = QTableView()
        self.HotSearch_tableView.setModel(self.HotSearch_model)
        self.HotSearch_tableView.horizontalHeader().setMinimumHeight(40)
        self.HotSearch_tableView.setColumnWidth(0, 200)
        self.HotSearch_tableView.setColumnWidth(1, 1000)

        # 历史热门表格
        self.HistoricalTopic_model = QStandardItemModel()
        self.HistoricalTopic_model.setHorizontalHeaderLabels(self.HistoricalTopic_attribute)

        self.HistoricalTopic_tableView = QTableView()
        self.HistoricalTopic_tableView.setModel(self.HistoricalTopic_model)
        self.HistoricalTopic_tableView.horizontalHeader().setMinimumHeight(40)
        self.HistoricalTopic_tableView.setColumnWidth(0, 650)
        self.HistoricalTopic_tableView.setColumnWidth(1, 180)
        self.HistoricalTopic_tableView.setColumnWidth(2, 90)
        self.HistoricalTopic_tableView.setColumnWidth(3, 180)
        self.HistoricalTopic_tableView.setColumnWidth(4, 90)
        self.HistoricalTopic_tableView.setVisible(False)

        # 话题排行表格
        self.TopicCount_model = QStandardItemModel()
        self.TopicCount_model.setHorizontalHeaderLabels(self.TopicCount_attribute)

        self.TopicCount_tableView = QTableView()
        self.TopicCount_tableView.setModel(self.TopicCount_model)
        self.TopicCount_tableView.horizontalHeader().setMinimumHeight(40)
        self.TopicCount_tableView.setColumnWidth(0, 100)
        self.TopicCount_tableView.setColumnWidth(1, 350)
        self.TopicCount_tableView.setColumnWidth(2, 650)
        self.TopicCount_tableView.setVisible(False)

        # 水平方向标签拓展剩下的窗口部分，填满表格
        self.HotSearch_tableView.horizontalHeader().setStretchLastSection(True)
        self.HistoricalTopic_tableView.horizontalHeader().setStretchLastSection(True)
        self.TopicCount_tableView.horizontalHeader().setStretchLastSection(True)

        # label
        self.label_title = QLabel()
        self.label_title.setPixmap(QPixmap('images/title.png'))
        self.label_title.setMaximumHeight(150)
        self.label_title.setAlignment(Qt.AlignHCenter)

        self.label_WB_logo = QLabel()
        self.label_WB_logo.setPixmap(QPixmap('images/WB_logo.png'))
        self.label_WB_logo.setMaximumHeight(60)
        self.label_WB_logo.setAlignment(Qt.AlignHCenter)

        self.label_HistoricalTopic_Tip = QLabel()
        self.label_HistoricalTopic_Tip.setText('<font size=7>历史热门数据获取中</font>')
        self.label_HistoricalTopic_Tip.setAlignment(Qt.AlignHCenter)
        self.label_HistoricalTopic_Tip.setVisible(False)

        self.label_TopicCount_Tip = QLabel()
        self.label_TopicCount_Tip.setText('<font size=7>话题排行数据获取中</font>')
        self.label_TopicCount_Tip.setAlignment(Qt.AlignHCenter)
        self.label_TopicCount_Tip.setVisible(False)

        self.label_barGraph_TipOrImage = QLabel()
        self.label_barGraph_TipOrImage.setText('<font size=7>标签统计数据获取中</font>')
        self.label_barGraph_TipOrImage.setAlignment(Qt.AlignHCenter)
        self.label_barGraph_TipOrImage.setVisible(False)

        self.label_wordcloud_TipOrImage = QLabel()
        self.label_wordcloud_TipOrImage.setText('<font size=7>热词数据获取中</font>')
        self.label_wordcloud_TipOrImage.setAlignment(Qt.AlignHCenter)
        self.label_wordcloud_TipOrImage.setVisible(False)

        # button
        self.btn_RealtimeHotSearch = QPushButton('实时热搜')
        self.btn_RealtimeHotSearch.setCheckable(True)
        self.btn_RealtimeHotSearch.toggle()
        self.btn_RealtimeHotSearch.setIcon(QIcon(QPixmap('images/btn_RealtimeHotSearch_icon.png')))
        self.btn_RealtimeHotSearch.clicked.connect(self.btn_HotSearch_click)
        self.btn_RealtimeHotSearch.setMaximumWidth(90)

        self.btn_HistoricalTopic = QPushButton('历史热门')
        self.btn_HistoricalTopic.setCheckable(True)
        self.btn_HistoricalTopic.setIcon(QIcon(QPixmap('images/btn_HistoricalTopic_icon.png')))
        self.btn_HistoricalTopic.clicked.connect(self.btn_HistoricalTopic_click)
        self.btn_HistoricalTopic.setMaximumWidth(90)

        self.btn_TopicCount = QPushButton('话题排行')
        self.btn_TopicCount.setCheckable(True)
        self.btn_TopicCount.setIcon(QIcon(QPixmap('images/btn_TopicCount_icon.png')))
        self.btn_TopicCount.clicked.connect(self.btn_TopicCount_click)
        self.btn_TopicCount.setMaximumWidth(90)

        self.btn_tagStatistics = QPushButton('标签统计')
        self.btn_tagStatistics.setCheckable(True)
        self.btn_tagStatistics.setIcon(QIcon(QPixmap('images/btn_tagStatistics_icon.png')))
        self.btn_tagStatistics.clicked.connect(self.btn_bar_graph_click)
        self.btn_tagStatistics.setMaximumWidth(90)

        self.btn_wordcloud = QPushButton('热词词云')
        self.btn_wordcloud.setCheckable(True)
        self.btn_wordcloud.setIcon(QIcon(QPixmap('images/btn_wordcloud_icon.png')))
        self.btn_wordcloud.clicked.connect(self.btn_wordcloud_click)
        self.btn_wordcloud.setMaximumWidth(90)

        # 主按钮的按钮组
        self.btn_group = QButtonGroup()
        self.btn_group.addButton(self.btn_RealtimeHotSearch, 1)
        self.btn_group.addButton(self.btn_HistoricalTopic, 2)
        self.btn_group.addButton(self.btn_TopicCount, 3)
        self.btn_group.addButton(self.btn_tagStatistics, 4)
        self.btn_group.addButton(self.btn_wordcloud, 5)
        self.btn_group.setExclusive(True)

        # 日历
        self.calendar = QCalendarWidget()
        self.calendar.setMinimumDate(QDate(1980, 1, 1))
        self.calendar.setMaximumDate(QDate(3000, 1, 1))
        self.calendar.setGridVisible(True)
        self.calendar.move(20, 20)
        self.calendar.clicked[QDate].connect(self.choose_date)

        calendarLayout = QVBoxLayout()
        calendarLayout.addWidget(self.calendar)

        # 显示日历的对话框
        self.dialog = QDialog()
        self.dialog.setWindowTitle('选择要查看的热门话题的日期')
        self.dialog.setWindowIcon(QIcon('images/calendar_icon.png'))
        self.dialog.resize(400, 350)
        self.dialog.setWindowModality(Qt.ApplicationModal)
        self.dialog.setLayout(calendarLayout)

        # 历史热门界面下的选择日期按钮
        self.btn_choose_date = QPushButton('选择日期')
        self.btn_choose_date.setCheckable(False)
        self.btn_choose_date.setIcon(QIcon(QPixmap('images/calendar_icon.png')))
        self.btn_choose_date.setMaximumWidth(90)
        self.btn_choose_date.clicked.connect(self.btn_choose_date_click)
        self.btn_choose_date.setVisible(False)

        # 布局
        hbox = QHBoxLayout()
        vbox1 = QVBoxLayout()
        vbox2 = QVBoxLayout()

        vbox1.addStretch(5)
        vbox1.addWidget(self.btn_RealtimeHotSearch)
        vbox1.addStretch(1)
        vbox1.addWidget(self.btn_HistoricalTopic)
        vbox1.addStretch(1)
        vbox1.addWidget(self.btn_TopicCount)
        vbox1.addStretch(1)
        vbox1.addWidget(self.btn_tagStatistics)
        vbox1.addStretch(1)
        vbox1.addWidget(self.btn_wordcloud)
        vbox1.addStretch(5)

        vbox2.addWidget(self.label_title)
        vbox2.addWidget(self.label_WB_logo)
        vbox2.addWidget(self.btn_choose_date)
        vbox2.addWidget(self.label_HistoricalTopic_Tip)
        vbox2.addWidget(self.label_TopicCount_Tip)
        vbox2.addWidget(self.label_barGraph_TipOrImage)
        vbox2.addWidget(self.label_wordcloud_TipOrImage)
        vbox2.addWidget(self.HotSearch_tableView)
        vbox2.addWidget(self.HistoricalTopic_tableView)
        vbox2.addWidget(self.TopicCount_tableView)

        hbox.addLayout(vbox1)
        hbox.addLayout(vbox2)

        self.setLayout(hbox)

        # 启动实时热搜、历史热门线程
        self.getRealTimeHotSearchThread.start()
        self.getTableDataThread.start()

    # 更新实时热搜表格
    def update_HotSearchTable(self, HotSearch_data):
        self.HotSearch_model.setRowCount(0)
        for row in range(len(HotSearch_data)):
            for column in range(len(self.HotSearch_attribute)):
                if HotSearch_data[row][column] == '' and column == 0:
                    item = QStandardItem('榜顶')
                    item.setForeground(QColor('#ff0000'))
                elif HotSearch_data[row][column] == '热' and column == 2:
                    item = QStandardItem('热')
                    item.setForeground(QColor('#ff9406'))
                elif HotSearch_data[row][column] == '沸' and column == 2:
                    item = QStandardItem('沸')
                    item.setForeground(QColor('#f86400'))
                elif HotSearch_data[row][column] == '荐' and column == 2:
                    item = QStandardItem('荐')
                    item.setForeground(QColor('#00b7ee'))
                elif HotSearch_data[row][column] == '新' and column == 2:
                    item = QStandardItem('新')
                    item.setForeground(QColor('#ff3852'))
                else:
                    item = QStandardItem(HotSearch_data[row][column])
                self.HotSearch_model.setItem(row, column, item)
        self.HotSearch_tableView.setModel(self.HotSearch_model)

    # 获取实时热搜数据失败，输出错误信息到控制台
    def failure_getHotSearch(self, error_code):
        print('获取实时热搜失败 ErrorCode:' + str(error_code))

    # 加载历史热门表格数据
    def load_HistoricalTopicTable_data(self, HistoricalTopic_data):
        self.HistoricalTopic_model.setRowCount(0)
        for row in range(len(HistoricalTopic_data)):
            for column in range(len(self.HistoricalTopic_attribute)):
                item = QStandardItem(HistoricalTopic_data[row][column])
                self.HistoricalTopic_model.setItem(row, column, item)
        self.HistoricalTopic_tableView.setModel(self.HistoricalTopic_model)
        self.init_HistoricalTopic_flag = True
        if self.btn_HistoricalTopic.isChecked():
            self.label_HistoricalTopic_Tip.setVisible(False)
            self.btn_choose_date.setVisible(True)
            self.HistoricalTopic_tableView.setVisible(True)

    def btn_HotSearch_click(self):
        self.label_HistoricalTopic_Tip.setVisible(False)
        self.label_TopicCount_Tip.setVisible(False)
        self.btn_choose_date.setVisible(False)
        self.HistoricalTopic_tableView.setVisible(False)
        self.label_barGraph_TipOrImage.setVisible(False)
        self.label_wordcloud_TipOrImage.setVisible(False)
        self.TopicCount_tableView.setVisible(False)
        self.HotSearch_tableView.setVisible(True)

    def btn_HistoricalTopic_click(self):
        self.label_TopicCount_Tip.setVisible(False)
        self.HotSearch_tableView.setVisible(False)
        self.label_barGraph_TipOrImage.setVisible(False)
        self.label_wordcloud_TipOrImage.setVisible(False)
        self.TopicCount_tableView.setVisible(False)
        if not self.init_HistoricalTopic_flag:
            self.btn_choose_date.setVisible(False)
            self.HistoricalTopic_tableView.setVisible(False)
            self.label_HistoricalTopic_Tip.setVisible(True)
        else:
            self.label_HistoricalTopic_Tip.setVisible(False)
            self.btn_choose_date.setVisible(True)
            self.HistoricalTopic_tableView.setVisible(True)

    def btn_TopicCount_click(self):
        self.label_HistoricalTopic_Tip.setVisible(False)
        self.HotSearch_tableView.setVisible(False)
        self.btn_choose_date.setVisible(False)
        self.HistoricalTopic_tableView.setVisible(False)
        self.label_barGraph_TipOrImage.setVisible(False)
        self.TopicCount_tableView.setVisible(False)
        self.label_wordcloud_TipOrImage.setVisible(False)
        self.label_TopicCount_Tip.setText('<font size=7>话题排行数据获取中</font>')
        self.label_TopicCount_Tip.setVisible(True)
        self.getTopicListThread.start()

    def btn_bar_graph_click(self):
        self.label_HistoricalTopic_Tip.setVisible(False)
        self.label_TopicCount_Tip.setVisible(False)
        self.HotSearch_tableView.setVisible(False)
        self.btn_choose_date.setVisible(False)
        self.HistoricalTopic_tableView.setVisible(False)
        self.TopicCount_tableView.setVisible(False)
        self.label_wordcloud_TipOrImage.setVisible(False)
        self.label_barGraph_TipOrImage.setText('<font size=7>标签统计数据获取中</font>')
        self.label_barGraph_TipOrImage.setVisible(True)
        self.getTagListThread.start()

    def btn_wordcloud_click(self):
        self.label_HistoricalTopic_Tip.setVisible(False)
        self.label_TopicCount_Tip.setVisible(False)
        self.HotSearch_tableView.setVisible(False)
        self.btn_choose_date.setVisible(False)
        self.HistoricalTopic_tableView.setVisible(False)
        self.TopicCount_tableView.setVisible(False)
        self.label_barGraph_TipOrImage.setVisible(False)
        self.label_wordcloud_TipOrImage.setText('<font size=7>热词数据获取中</font>')
        self.label_wordcloud_TipOrImage.setVisible(True)
        self.getWordDictThread.start()

    def btn_choose_date_click(self):
        self.dialog.exec_()

    def choose_date(self, date):
        date_msg = date.toString('yyyy MM dd')
        self.getTableDataThread = utils.GetTableDataThread(0, date_msg)
        self.getTableDataThread.get_table_data.connect(self.load_HistoricalTopicTable_data)
        self.getTableDataThread.start()

    # 加载话题排行表格数据
    def load_TopicCountTable_data(self, topic_list):
        self.TopicCount_model.setRowCount(0)
        for row in range(len(topic_list)):
            for column in range(len(self.TopicCount_attribute) - 1):
                item = QStandardItem(topic_list[row][column])
                rank_value = QStandardItem('Top ' + str(row + 1))
                self.TopicCount_model.setItem(row, 0, rank_value)
                self.TopicCount_model.setItem(row, column + 1, item)
        self.TopicCount_tableView.setModel(self.TopicCount_model)
        if self.btn_TopicCount.isChecked():
            self.label_TopicCount_Tip.setVisible(False)
            self.TopicCount_tableView.setVisible(True)

    # 生成标签统计图
    def create_barGraph(self, tag_list):
        tag_name = tag_list[0]
        tag_frequency = tag_list[1]
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        fig = plt.figure(figsize=(14, 6.5))
        fig.canvas.set_window_title('标签频次')
        plt.xlabel('名称', size=15)
        plt.ylabel('频次', size=15)
        count_time = datetime.datetime.now() + datetime.timedelta(days=-1)
        title = '各个标签的频次统计图\n（统计截止至' + str(count_time)[0:10] + ' 22:00:00' + '）'
        plt.title(title, size=20)

        bar = plt.bar(tag_name, tag_frequency, alpha=0.7, width=0.8, facecolor='steelblue')

        for item in bar:
            height = item.get_height()
            plt.text(item.get_x() + item.get_width() / 2, height, height, ha='center', va='bottom')
            item.set_edgecolor('white')
        plt.savefig('images/tag_image.png')
        self.label_barGraph_TipOrImage.setPixmap(QPixmap('images/tag_image.png'))

    # 生成热词词云
    def create_wordcloud(self, word_dict):
        cloud_image = 'images/cloud.png'
        font = 'fonts/miniJianQi.TTF'

        mask = imageio.imread(cloud_image)

        # 词云字体颜色范围
        def random_color_func(word=None, font_size=None, position=None, orientation=None, font_path=None,
                              random_state=None):
            h = random.randint(0, 255)
            s = int(100.0 * 255.0 / 255.0)
            l = int(100.0 * float(random.randint(60, 120)) / 255.0)
            return "hsl({}, {}%, {}%)".format(h, s, l)

        cloud = wordcloud.WordCloud(font_path=font, mask=mask, background_color='white', color_func=random_color_func)

        cloud.generate_from_frequencies(word_dict)
        cloud.to_file('images/wordcloud_image.png')
        self.label_wordcloud_TipOrImage.setPixmap(QPixmap('images/wordcloud_image.png'))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    try:
        sys.exit(app.exec_())
    except SystemExit as msg:
        print('Exit Code:' + str(msg))
